function [y,z]=neighbor_predict(dt,x,Ind)

%NEIGHBOR_PREDICT uses closest neighbor committee to make predictions
%Syntax: [y,z]=neighbor_predict(dt,x)
%Description: dt is a data structure of the type produced by
%             var_select_neighbor_val.m and y is a vector of predictions.
%             x contains the independent parameter values and can be either
%             the name of the tsv file as the one read by read_data.m* to
%             produce dt in the first place. If dt is a string this command
%             will be read as neighbor_predict(x) and dt will be retrieved
%             from the path directories.
%
%             example: y=neighbor_predict('normCtValues.tsv')
%
%             * first column has sample names and subsequent columns have
%             the RTPCR data. First row contains gene names
%
%Jonas Almeida, 21 Feb 2005

%processing variation son input argument format
if ischar(dt)
    x=dt;
    load dt
else
    if nargin<2
        x=dt.nx; % this would be an internal validation exercise
    elseif isempty(x)
        x=dt.nx; % this would be an internal validation exercise
    end
end
z.nx=x;
% find out what was the best commitee
%[lala,Ind]=min(sum(dt.predict.err));
if nargin<3
    [lala,Ind]=min(sum(dt.predict.dy)); % Optimal committee size
end 
%Ask each committee member:
[n,m]=size(dt.predict.var);
ref_x=dt.nx;ref_y=dt.y;
for i=1:n
    %ref_x=dt.nx;ref_y=dt.y;ref_x(i,:)=[];ref_y(i)=[];[z.y(:,i),z.N(:,i)]=neighbors_y(ref_x(:,dt.predict.var(i,1:Ind)),ref_y,z.nx(i,dt.predict.var(i,1:Ind))); %this only make sense if this is cross-validation
    [z.y(:,i),z.N(:,i),z.D(:,i)]=neighbors_y(dt.nx(:,dt.predict.var(i,1:Ind)),dt.y,z.nx(:,dt.predict.var(i,1:Ind)));
end
z.OptN=Ind;
%pool the committee votes:
y=mean(z.y,2);

% ------------- nested functions, for stand alone delivery ---------------------
% ------------- make sure they are updated before delivery ---------------------

function [y,dt]=memb(xo,dt)

% function [y,dt]=memb(xo,dt)
% builds membership function
% xo: raw data
% y: xo represented as membership
% dt: distribution (two column matrix)
%     if not provided it will be calculated

%disp(':-)')
if nargin<2
   x=sort(xo(:));
   n=length(x);
   sx=(0:(1/(n-1)):1)';
   % Cut repeats
   rep_i=find(x(1:end-1)==x(2:end))+1;
   x(rep_i)=[];sx(rep_i)=[];
   % rescaling between 0 and 1
   % sx=(sx-sx(1))/(sx(end)-sx(1));
   dt=[x,sx];
end

y=interp1(dt(:,1),dt(:,2),xo);

function [y,N,D]=neighbors_y(train_x,train_y,test_x)

%NEIGHBORS_Y assigns to test values the outcome of that of the closest neighbour in the training set
%Syntax: [y,N,D]=neighbors_y(train_x,train_y,test_x)
%Description: each column documents a variable and each row an event / sample 
%             y is the predicted outcome and N is the index of the closest
%             neighbor, where that outcome took place.
%
%
%Jonas Almeida, 16 Feb 2006

n=length(test_x(:,1));
m=length(train_x(:,1));N=zeros(n,1);D=N;
for i=1:n
    [D(i),N(i)]=min(sum((train_x-repmat(test_x(i,:),m,1)).^2,2)); %Euclidean distances between ith test x and all training xs
end
y=train_y(N,:);